<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <script src="./js/vue.js"></script>
    <style>
        #app {
            border: 2px solid red;
            padding: 10px;
            margin-bottom: 200px
        }

        .child {
            margin: 20px;
            padding: 10px;
            background-color: skyblue;
        }
    </style>
</head>

<body>
    <div id="app">
        <h3>父组件控件</h3>
        <p>msg:{{msg}}</p>
        <input type="text" v-model="msg">
        <child-one></child-one>
        <p>arr:{{arr}}</p>
        <input type="text" v-for="(item, index) in arr" v-model="arr[index]">
        <child-two v-for="(item, index) in arr" :key="index" aaa="aaaa" b="b" v-bind:item=" item "></child-two>
        <p>info:{{ info }}</p>
        <input type="text" v-model="info">
        <p>num:{{ num }}</p>
        <input type="text" v-model="num">
        <child-three :info=" info " :num=" num " :user=" user " :arr=" [2,3,4] " :number=" 11 "></child-three>
    </div>



    <template id=ChildOne>
        <div class="child">
            <h3>子组件范围</h3>
            <p>msg:{{msg}}</p>
            <input type="button" value="获取父组件实例" @click="printparent()">
        </div>
    </template>



    <template id="ChildTwo">
        <div class="child">
            <h3>子组件范围</h3>
            <p>item:{{item}}</p>
            <input type="button" value="打印$attrs" @click="printAttrs()">

        </div>
    </template>



    <template id="ChildThree">
        <div class="child">
            <h3>子组件范围</h3>
            <p>info:{{info}}</p>
            <input type="text" v-model="info">
            <input type="button" value="修改info" @click=" info='新值' ">
            <p>num:{{num}}</p>
            <hr>
            <p>user:{{user.name}}</p>
            <hr>
            <p>arr:{{arr}}</p>
            <!-- number 数据必须在 10 ~ 20 直接 -->
            <p>number:{{ number }}</p>
        </div>
    </template>
</body>
<script>
    // 子组件主动获取（不具有响应式的特性 = 父组件的数据变化不能主动传递给子组件）
    /*
        使用实例属性 $parent 进行数据加载
            $parent 如果当前组件存在父组件，通过$parent 可以获取父组件实例
            借助于生命周期钩子函数完成，数据的主动赋值操作，启动响应式原理更新页面
            只能获取父组件已知的数据变量
    */
    Vue.component("ChildOne", {
        template: "#ChildOne",
        data() {
            return {
                msg: ""
            }
        },
        methods: {
            printparent() {
                console.log(this.$parent);
                console.log(this.$parent.msg);
                this.msg = this.$parent.msg;
            }
        },
        mounted() {
            this.msg = this.$parent.msg;
        }
    })

    /*
         使用实例属性 $attrs 进行数据加载
             $attrs 是用于获取在当前组件标签上，使用自定义属性方式绑定的数据变量
 
    */
    Vue.component("ChildTwo", {
        template: "ChildTwo",
        data() {
            return {
                item: ""
            }
        },
        methods: {
            printAttrs() {
                console.log(this.$attrs);
            }
        },
        mounted() {
            this.item = this.$attrs.item
        },
    })
    /*
        子组件的被动获取
            使用vue实例构建时的属性 props ，进行组件标签自定义属性的变量拦截
            并将拦截的变量关联父组件相关变量，定义响应式数据劫持操作，劫持操作只定义 get 方法 
            props 属性 为vue实例的，定义父组件传递数据的拦截仓库，该仓库和data仓库操作行为基本相同
                但 props 为只读仓库
            props 取值 Array | Object
                Array ：数组中以字符串的方式， 定义需要拦截的自定义属性名称
                Object ：对象中以详细描述的方式 严格限制 传递数据信息（数据校验）
                    * 数据校验，不是为使用者定义的功能，市委开发者定义的功能
                    * 提示开发人员调用组件时，是否出现了参数传去错误的问题
    */
    Vue.component("ChildThree", {
        template: "#ChildThree",
        // props:["info","num","user"]
        props: {
            // key:value
            // key 被拦截的属性名称
            // value 可以取值  Type | Object
            //      Type 是JS 的数据类型 构造器 ，描述该属性必须为指定的数据类型
            //      Object 是以 vue 内置的校验属性 进行更加细致的功能检测
            info: String,
            num: Number,
            user: {
                // 类型限制
                type: Object,
                // 当前数据变量为 组件调用时必传属性 true|false(默认)
                required: true
            },
            arr: {
                // type:String,
                type: Array,
                // 用于描述组件标签如果没有绑定该属性，使用默认值
                //   1、基本类型的默认值定义
                // default:"默认值"
                //   2、引用类型的默认值定义,取值方法return默认值
                default: function () {
                    return [1, 2, 3];
                }
            },
            number: {
                // 自定义传入数据的校验规则
                // value 为传递的数据变量
                validator: function (value) {
                    if (typeof value === "number") {
                        if (value > 10 && value < 20) {
                            return true; // 表示校验通过
                        } else {
                            console.error("number必须大于10小于20")
                            return false // 表示校验失败
                        }
                    } else {
                        console.error("number必须是数值类型")
                        return false;
                    }
                }
            }
        }
    });

    new Vue({
        el: "#app",
        data: {
            msg: "字符串msg",
            arr: ["数据1", "数据2"],
            info: "info字符串",
            num: 30,
            user: {}
        }
    })
</script>

</html>